#include "stdafx.h"
#include "RenderViewport.h"
#include <LitCore.h>

RenderViewport::RenderViewport(QWidget* parent) 
	: QWidget( parent )
	, mSettings( NULL )
	, mLastFrameTime( 0.0f )
{
	mLayout = new QVBoxLayout( this );
	setLayout( mLayout );
	
    mOgreWidget = new OgreWidget(this);

	mLayout->addWidget( mOgreWidget );
	setAcceptDrops( true );
	mMenu = new QMenu(this);


	connect( mOgreWidget, SIGNAL(ogreInitialise()), this, SLOT(ogreInitialise()) );
	connect( mOgreWidget, SIGNAL(ogreShutdown()), this, SLOT(ogreShutdown()) );

	setMouseTracking(true);
	mOgreWidget->setMouseTracking(true);

}
RenderViewport::~RenderViewport( )
{
	mCamCtl.destroy();
	mUserQuery.destroy();
	mDrag.destroy();
	mCamDrag.destroy();
	if( mMenu ) delete mMenu, mMenu = NULL;
	if( mSettings ) delete mSettings, mSettings = NULL;
	mOgreWidget->ogreRoot()->removeFrameListener(this);
	if( mOgreWidget ) delete mOgreWidget, mOgreWidget = NULL;
	if( mLayout ) delete mLayout, mLayout = NULL;
}

void RenderViewport::ogreInitialise( )
{
	mOgreWidget->ogreRoot()->addFrameListener(this);
}

void RenderViewport::ogreShutdown()
{
}

bool RenderViewport::eventFilter( QObject*obj, QEvent*evt ){
	if( evt->type() == QEvent::MouseButtonPress )
	{
		mousePressEvent( (QMouseEvent*)evt );
	}
	if( evt->type() == QEvent::MouseButtonRelease )
	{
		mouseReleaseEvent( (QMouseEvent*)evt );
	}
	if( evt->type() == QEvent::MouseMove )
	{
		mouseMoveEvent( (QMouseEvent*)evt );
	}
	
	if( evt->type() == QEvent::KeyPress )
	{
		emit keyPressSignal( (QKeyEvent*)evt );
	}
	if( evt->type() == QEvent::KeyRelease )
	{
		emit keyReleaseSignal( (QKeyEvent*)evt );
	}
	return false;
}
	
void RenderViewport::_mouseDrag( UserDragEvent evt, UserDragPtr drag )
{
	if( evt == UDE_UPDATE && drag->button() == UDB_LEFT )
	{
		mUserQuery->execute( mOgreWidget->ogreCamera(), mDrag->start(), mDrag->end() );
	}
	switch( drag->button() )
	{
		case UDB_LEFT:
		{
			break;
		}
		case UDB_RIGHT:
		{
			break;
		}
	};
}
void RenderViewport::_cameraDrag( UserDragEvent evt, UserDragPtr drag )
{
	switch( drag->button() )
	{
		case UDB_MIDDLE:
		{
			if( evt == UDE_UPDATE )
			{
				Lit::Vec2 delta = drag->deltaFactor(1.0f);
				mCamCtl->updateMouse( delta.x, delta.y, mLastFrameTime );
			}
			break;
		}
	};
}

void RenderViewport::showSettings( Lit::ResourcesList * res ){
}
void RenderViewport::mousePressEvent( QMouseEvent * evt ){
	UserDragButton btn;
	if( evt->button() == Qt::LeftButton ) 
	{
		mDrag->initDrag( evt->pos(), UDB_LEFT );
	}
	else if( evt->buttons() == Qt::RightButton )
	{
		mDrag->initDrag( evt->pos(), UDB_RIGHT );
	}
	else if( evt->buttons() == Qt::MidButton )
	{
		mCamDrag->initDrag( evt->pos(), UDB_MIDDLE );
	}
	emit mousePressSignal( evt );
}
UserDragPtr RenderViewport::mouseDrag() const{ return mDrag; }
UserDragPtr	RenderViewport::cameraDrag() const{ return mCamDrag; }
UserQueryPtr RenderViewport::userQuery(){ return mUserQuery; }
const QMenu * RenderViewport::menu() const{ return mMenu; }
QMenu* RenderViewport::menu(){ return mMenu; }
	
Ogre::Ray RenderViewport::getUserRay(){
	QPoint local = mOgreWidget->mapFromGlobal( QCursor::pos() );
	Lit::Vec2 d( UserDrag::mouseWidgetRatio( local, mOgreWidget->geometry() ) );
	return mOgreWidget->ogreCamera()->getCameraToViewportRay(d.x, d.y);
}
void RenderViewport::mouseMoveEvent( QMouseEvent * evt ){
	mDrag->updateDrag( evt->pos() );
	mCamDrag->updateDrag(evt->pos());
	emit mouseMoveSignal( evt );
}
void RenderViewport::mouseReleaseEvent( QMouseEvent*evt ){
	if( evt->button() != Qt::MidButton )
	{
		if( evt->button() == Qt::RightButton )
		{
			if( Lit::Root::SceneManager()->getSelection()->empty() )
			{
				mUserQuery->execute( mOgreWidget->ogreCamera(), mDrag->start(), mDrag->end() );
				emit updateSceneSelection( mUserQuery->lastResult() );
			}
			Lit::Vec2 d = UserDrag::mouseWidgetRatio( evt->pos(), mOgreWidget->geometry() );
			emit renderMenuRequested( d.x, d.y );
		}
		else 
		{
			mUserQuery->execute( mOgreWidget->ogreCamera(), mDrag->start(), mDrag->end() );
			emit updateSceneSelection( mUserQuery->lastResult() );
		}
	}
	emit mouseReleaseSignal( evt );
	mDrag->closeDrag( evt->pos() );
	if( evt->button() == Qt::MidButton ) mCamDrag->closeDrag( evt->pos() );
}

bool RenderViewport::frameRenderingQueued( const Ogre::FrameEvent& evt )
{
	mLastFrameTime = evt.timeSinceLastFrame;
	mCamCtl->updateKeyboard( mLastFrameTime );
	/*
	if( GetAsyncKeyState( 'W' ) & 0x8000 )	mOgreWidget->ogreCamera()->move( mOgreWidget->ogreCamera()->getDirection().normalisedCopy() * evt.timeSinceLastFrame*10.0 );
	if( GetAsyncKeyState( 'S' ) & 0x8000 )	mOgreWidget->ogreCamera()->move( -mOgreWidget->ogreCamera()->getDirection().normalisedCopy() * evt.timeSinceLastFrame*10.0 );
	if( GetAsyncKeyState( 'A' ) & 0x8000 )	mOgreWidget->ogreCamera()->move( -mOgreWidget->ogreCamera()->getRight().normalisedCopy() * evt.timeSinceLastFrame*10.0 );
	if( GetAsyncKeyState( 'D' ) & 0x8000 )	mOgreWidget->ogreCamera()->move( mOgreWidget->ogreCamera()->getRight().normalisedCopy() * evt.timeSinceLastFrame*10.0 );
	*/
	return true;
}
void RenderViewport::dropEvent( QDropEvent * evt ){
	if (evt->mimeData()->hasText()){}
		//dataLabel->setText(evt->mimeData()->text());
	else if (evt->mimeData()->hasImage()) {
		QVariant imageData = evt->mimeData()->imageData();
		//dataLabel->setPixmap(qvariant_cast<QPixmap>(imageData));
	}
	evt->acceptProposedAction();
}
void RenderViewport::showEvent( QShowEvent*evt )
{
	QWidget::showEvent(evt);
	
	if( !mSceneMgr ){
		mSceneMgr = Lit::Root::SceneManager();
		mDrag = new UserDrag(mOgreWidget, UDF_BUTTON_RELEASE_DELTA, boost::bind( &RenderViewport::_mouseDrag, this, _1, _2 ));
		mCamDrag = new UserDrag(mOgreWidget, UDF_FRAME_DELTA, boost::bind( &RenderViewport::_cameraDrag, this, _1, _2 ));
		mUserQuery = new UserSceneQuery( mOgreWidget, mSceneMgr );
		mOgreWidget->installEventFilter( this );
		mCamCtl = new CameraController( mOgreWidget->ogreCamera(), 50.0f, 50.0f );
	}
}

OgreWidget* RenderViewport::ogreWidget() const{ return mOgreWidget; }
